﻿using UnityEngine;
using System.Collections;
using Pathfinding;
using System;
using System.Collections.Generic;


[RequireComponent(typeof(Seeker))]
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(SteveBrain))]
public class StevePathfindedController : MonoBehaviour {

    
    public float speed = 2f;
    public float nextWaypointDistance = 0.75f;

    private EventDelegate callbackOnEndPath;
    private int currentWaypointIndex;
    private bool stopped;
    private Path path;
    
    
    void Awake(){
        this.stopped = true;
        this.currentWaypointIndex = 0;
    }

	void FixedUpdate () {
        Seeker seeker = this.GetComponent<Seeker>();

        //checks if there's an AStarPath global active component in the scene
        if (AstarPath.active != null) {
            //then checks if the component is not scanning the scene and if the seeker
            //associated with this gameobject has finished searching a path.
            if (!AstarPath.active.isScanning && seeker.IsDone()) { 
                //then checks if this character controller has not been stopped
                if (!this.stopped && path!=null) {
                    //if there's another unvisited waypoint on the current path to destination
                    //then let's go for it.
                    if (currentWaypointIndex < path.vectorPath.Count) {
                        Vector3 currentWaypoint = path.vectorPath[currentWaypointIndex];
                        this.moveCharacter(currentWaypoint);

                        Vector3 distanceFromWaypoint = this.transform.position - currentWaypoint;
                        if (distanceFromWaypoint.sqrMagnitude < this.nextWaypointDistance) {
                            currentWaypointIndex++;
                            return;
                        }
                    }else if(currentWaypointIndex == path.vectorPath.Count) {
                        //otherwise we stop the gameobject
                        if (this.callbackOnEndPath != null) {
                            this.callbackOnEndPath.Execute();
                        }
                        this.Stop();
                    }
                }   
            }
        }
	}

    private void onPathSearchCompleted(Path p){
        p.Claim(this);
        if (!p.error){
            if (path != null) {
                path.Release(this);
            } 
            path = p;
        }else{
            p.Release(this);
            Debug.Log("Oh noes, the target was not reachable: " + p.errorLog);
        }
    }

    public void SetTarget(Vector3 target , EventDelegate callback){
        Seeker seeker = this.GetComponent<Seeker>();
        this.callbackOnEndPath = callback;
        this.currentWaypointIndex = 0;
        this.stopped = false;
        seeker.StartPath(this.transform.position, target, this.onPathSearchCompleted);
    }

    public void Stop(){
        this.stopped = true;
        this.stopCharacter();
    }

    private void moveCharacter(Vector3 wayPoint) {
        Animator animator = this.GetComponent<Animator>();
        Vector3 directPosition = new Vector3(wayPoint.x, 0, wayPoint.z); //evita problemi di angoli sbagliati
        Vector3 myPos = new Vector3(transform.position.x, 0, transform.position.z);
        Vector3 direction = directPosition - myPos;
        
        if (direction != Vector3.zero) {
            transform.rotation = Quaternion.LookRotation(direction);
        }
        transform.position = Vector3.MoveTowards(transform.position, wayPoint, Time.deltaTime * speed);
        animator.SetFloat("speed", speed);
    }

    private void stopCharacter() {
        Animator animator = this.GetComponent<Animator>();
        animator.SetFloat("speed", 0f);
    }
}
